﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CPlatePrintSys.Annotation.Events;
using CPlatePrintSys.Annotation.Models;
using CPlatePrintSys.Annotation.Controls;
using CPlatePrintSys.Domain.Events;
using CPlatePrintSys.Domain.Models;
using CPlatePrintSys.Domain.Services;
using CPlatePrintSys.Infrastructure;
using Newtonsoft.Json;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Navigation.Regions;
using netDxf.Entities;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Input;

namespace CPlatePrintSys.Annotation.ViewModels
{
    /// <summary>
    /// 基于Sheet的大小进行Parts布局的视图控件封装
    ///  1. Shee与Parts（每一个part对应dxf文件）的显示：
    ///     1.1 显示Sheet的规格大小（水平和垂直方向的显示尺寸标注：显示箭头和尺寸值类似cad中的尺寸标注）
    ///     1.2 1个sheet对应多个Parts的布局位置（Parts可以是不同的类型和尺寸，仅仅显示每个part的边界） 
    ///     1.3 Sheet和Part及标注的颜色可以自定义指定，默认采用不同给的颜色
    ///  2. Sheet中管理Parts的逻辑：
    ///     2.1 按照左下优先对齐的方式进行布局
    ///     2.2 新增一个part后，自动计算布局位置（如果有多个part，则按照左下对齐的方式进行布局）
    ///     2.3 删除一个part后，自动计算布局位置（如果有多个part，则按照左下对齐的方式进行布局）
    ///  3. 对于选中后的Part的布局位置编辑，支持以下功能：
    ///     3.1 点击Part的选择和高亮显示
    ///     3.2 选中Parts的拖拽和放置
    ///     3.3 对选中的Parts进行移动，旋转（以90度为单位）操作
    ///  4. 支持对Parts的布局位置进行保存和加载，相关的关系存储到一个json文件中，包含以下内容：
    ///     4.1 相关字段示例：
    ///     {
    ///         "SheetId": "Sheet的唯一标识符",
    ///         "Height": "Sheet的高度",
    ///         "Width": "Sheet的宽度",
    ///         "Parts": [
    ///             { 
    ///             "PartId": (唯一标识符),
    ///             "Path": (Part的dxf文件路径)   
    ///             "Position": (Part在Sheet中的位置，包含X和Y坐标)
    ///             "PartRotation": (Part在Sheet中的旋转角度)
    ///             }
    ///             ]
    ///         }
    ///   
    /// </summary>
    public class SheetLayoutViewModel : BindableBase
    {
        private readonly IEventAggregator _eventAggregator;
        private readonly IRegionManager _regionManager;
        private readonly ILayoutService _layoutService;
        private SheetLayoutInfo _currentSheet = new SheetLayoutInfo();

        // 当前选中part的Id
        private string _selectedPartId;

        // 当前合并的PlateAnnotationInfo列表
        private List<PlateAnnotationInfo> _currentMergedPlateAnnotationInfos;

        private double _sheetWidth;
        public double SheetWidth
        {
            get => _sheetWidth;
            set => SetProperty(ref _sheetWidth, value);
        }
        private double _sheetHeight;
        public double SheetHeight
        {
            get => _sheetHeight;
            set => SetProperty(ref _sheetHeight, value);
        }
        private string _specLayerName;
        public string SpecLayerName
        {
            get => _specLayerName;
            set => SetProperty(ref _specLayerName, value);
        }


        private string _subTitle = string.Empty;
        public string SubTitle
        {
            get { return _subTitle; }
            set { SetProperty(ref _subTitle, value); }
        }


        public DelegateCommand BackToHomeCommand { get; private set; }

        public DelegateCommand AddPartCommand { get; private set; }

        public DelegateCommand Rotate90DegreeCommand { get; private set; }

        public DelegateCommand RotateMinus90DegreeCommand { get; private set; }
        public DelegateCommand SaveLayoutCommand { get; private set; }

        public DelegateCommand RemoveGroupCommand { get; private set; }

        public SheetLayoutViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, ILayoutService layoutService)
        {
            _eventAggregator = eventAggregator;
            _regionManager = regionManager;
            _layoutService = layoutService;

            SubTitle = "合并图纸";

            // 初始化默认值
            SheetWidth = 1000.0;
            SheetHeight = 1000.0;
            SpecLayerName = "spec";

            BackToHomeCommand = new DelegateCommand(ExecuteBack);
            AddPartCommand = new DelegateCommand(OnAddPart);

            // 只需发布事件，由控件处理旋转和检测
            Rotate90DegreeCommand = new DelegateCommand(() => _eventAggregator.GetEvent<RotateSelectedPartEvent>().Publish(90));
            RotateMinus90DegreeCommand = new DelegateCommand(() => _eventAggregator.GetEvent<RotateSelectedPartEvent>().Publish(-90));
            SaveLayoutCommand = new DelegateCommand(async () => await SaveLayoutAsync());
            RemoveGroupCommand = new DelegateCommand(ExecuteRemoveGroup);

            _eventAggregator.GetEvent<StartDispalySheetLayoutEvents>().Subscribe(OnStartDisplaySheetLayout);

            this._eventAggregator.GetEvent<SheetLayoutAdjustEvent>().Subscribe(SheetLayoutAdjust);
        }

        private void SheetLayoutAdjust(List<PlateAnnotationInfo> partList)
        {
            // 保存当前的PlateAnnotationInfo列表，用于解除合并时使用
            _currentMergedPlateAnnotationInfos = partList;

            // 检查是否有已存在的布局信息
            var existingLayoutInfo = GetExistingLayoutInfo(partList);
            
            if (existingLayoutInfo != null && existingLayoutInfo.Merged != null)
            {
                // 加载已存在的布局信息
                LoadExistingLayout(existingLayoutInfo, partList);
            }
            else
            {
                // 创建新的布局
                CreateNewLayout(partList);
            }
        }

        /// <summary>
        /// 获取已存在的布局信息
        /// </summary>
        private LayoutInfo GetExistingLayoutInfo(List<PlateAnnotationInfo> partList)
        {
            try
            {
                // 查找第一个有布局信息的零件
                var partWithLayout = partList.FirstOrDefault(p => !string.IsNullOrEmpty(p.LayoutInfo));
                if (partWithLayout == null) return null;

                // 反序列化布局信息
                var layoutInfo = JsonConvert.DeserializeObject<LayoutInfo>(partWithLayout.LayoutInfo);
                return layoutInfo;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"获取已存在布局信息失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 加载已存在的布局
        /// </summary>
        private void LoadExistingLayout(LayoutInfo layoutInfo, List<PlateAnnotationInfo> partList)
        {
            try
            {
                System.Diagnostics.Debug.WriteLine("加载已存在的布局信息");
                
                // 设置钢板尺寸
                _currentSheet.Width = layoutInfo.Merged.SheetWidth;
                _currentSheet.Length = layoutInfo.Merged.SheetLongth;

                // 清空现有零件
                if (_currentSheet.Parts != null)
                    _currentSheet.Parts.Clear();
                _currentSheet.Parts = new List<PartLayoutInfo>();

                // 根据已保存的布局信息创建零件布局
                foreach (var partLayout in layoutInfo.Merged.PartLayouts)
                {
                    var partInfo = partList.FirstOrDefault(p => p.SheetConsistentNo == partLayout.SheetConsistentNo);
                    if (partInfo != null)
                    {
                        var partLayoutInfo = new PartLayoutInfo
                        {
                            Width = partInfo.DesignSpecLength,
                            Height = partInfo.DesignSpecWidth,
                            PartId = partInfo.SheetConsistentNo,
                            Path = partInfo.DesignDrawingPath,
                            // 设置已保存的位置和旋转信息
                            Position = new System.Windows.Point(partLayout.Position?.X ?? 0, partLayout.Position?.Y ?? 0),
                            PartRotation = partLayout.Rotation
                        };
                        
                        AddToDisplayNewPart(partLayoutInfo);
                    }
                }

                System.Diagnostics.Debug.WriteLine($"成功加载 {layoutInfo.Merged.PartLayouts.Count} 个零件的布局信息");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"加载已存在布局失败: {ex.Message}");
                // 如果加载失败，回退到创建新布局
                CreateNewLayout(partList);
            }
        }

        /// <summary>
        /// 创建新布局
        /// </summary>
        private void CreateNewLayout(List<PlateAnnotationInfo> partList)
        {
            System.Diagnostics.Debug.WriteLine("创建新布局");
            
            List<PartLayoutInfo> partLayouts = new List<PartLayoutInfo>();

            partList.ForEach(part =>
            {
                PartLayoutInfo partLayoutInfo = new PartLayoutInfo();
                partLayoutInfo.Width = part.DesignSpecLength;
                partLayoutInfo.Height = part.DesignSpecWidth;
                partLayoutInfo.PartId = part.SheetConsistentNo;
                partLayoutInfo.Path = part.DesignDrawingPath;
                partLayouts.Add(partLayoutInfo);
            });

            //TODO: 根据实际最大的Sheet判断而不是 计算最大钢板尺寸, 后续根据面积而不是简单的求最值
            var maxLength = partList.Max(s => s.SheetSpecLength);
            var maxWidth = partList.Max(s => s.SheetSpecWidth);

            _currentSheet.Width = maxWidth;
            _currentSheet.Length = maxLength;

            if (_currentSheet.Parts != null)
                _currentSheet.Parts.Clear();
            _currentSheet.Parts = new List<PartLayoutInfo>();

            partLayouts.ForEach(aPart => AddToDisplayNewPart(aPart));
        }

        private void ExecuteBack()
        {
            _regionManager.RequestNavigate(ConstStrings.UI_Region_Main_Content, "MainWindow");
        }


        private void OnAddPart()
        {
            // 1. 打开文件对话框选择dxf文件
            var dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.Filter = "DXF文件 (*.dxf)|*.dxf";
            dlg.Title = "选择要添加的零件DXF文件";
            if (dlg.ShowDialog() != true) return;
            string dxfPath = dlg.FileName;

            // 2. 封装方法提取PartLayoutInfo
            PartLayoutInfo newPart;
            try
            {
                newPart = ExtractPartLayoutInfoFromDxf(dxfPath);
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show($"DXF文件解析失败: {ex.Message}");
                return;
            }
            if (newPart == null)
            {
                System.Windows.MessageBox.Show("未能识别DXF中的零件边界。");
                return;
            }

            // 3. 自动寻找合适位置（左下优先）
            if (_currentSheet == null)
            {
                System.Windows.MessageBox.Show("请先初始化Sheet。");
                return;
            }
            if (_currentSheet.Parts == null)
                _currentSheet.Parts = new List<PartLayoutInfo>();

            AddToDisplayNewPart(newPart);
        }

        private void AddToDisplayNewPart(PartLayoutInfo newPart)
        {
            // 如果零件已经有位置信息（从已保存的布局加载），直接使用
            if (newPart.Position.X != 0 || newPart.Position.Y != 0)
            {
                System.Diagnostics.Debug.WriteLine($"使用已保存的位置: PartId={newPart.PartId}, Position=({newPart.Position.X}, {newPart.Position.Y}), Rotation={newPart.PartRotation}");
                _currentSheet.Parts.Add(newPart);
                _eventAggregator.GetEvent<DisplaySheetLayoutEvent>().Publish(_currentSheet);
                return;
            }

            // 否则自动计算位置
            double sheetW = _currentSheet.Length;
            double sheetH = _currentSheet.Width;
            double step = 10; // 步进精度
            bool found = false;
            double posX = 0, posY = 0;
            for (double y = 0; y + newPart.Height <= sheetH; y += step)
            {
                for (double x = 0; x + newPart.Width <= sheetW; x += step)
                {
                    // 检查是否与已有零件重叠
                    bool overlap = false;
                    foreach (var part in _currentSheet.Parts)
                    {
                        var rect1 = new Rect(x, y, newPart.Width, newPart.Height);
                        var rect2 = new Rect(part.Position.X, part.Position.Y, part.Width, part.Height);
                        if (rect1.IntersectsWith(rect2))
                        {
                            overlap = true;
                            break;
                        }
                    }
                    if (!overlap)
                    {
                        posX = x;
                        posY = y;
                        found = true;
                        break;
                    }
                }
                if (found) break;
            }
            if (!found)
            {
                System.Windows.MessageBox.Show("当前Sheet无法容纳该零件，请调整Sheet尺寸或移除部分零件。");
                return;
            }

            // 4. 设置位置并加入Sheet
            newPart.Position = new System.Windows.Point(posX, posY);
            _currentSheet.Parts.Add(newPart);

            // 5. 发布事件刷新显示
            _eventAggregator.GetEvent<DisplaySheetLayoutEvent>().Publish(_currentSheet);
        }

        /// <summary>
        /// 从dxf文件提取PartLayoutInfo（边界、宽高、路径、唯一ID等）
        /// </summary>
        public static PartLayoutInfo ExtractPartLayoutInfoFromDxf(string dxfPath)
        {
            var dxfDoc = netDxf.DxfDocument.Load(dxfPath);
            if (dxfDoc == null) throw new Exception("DXF文件无效或无法解析。");

            double minX = double.MaxValue, minY = double.MaxValue, maxX = double.MinValue, maxY = double.MinValue;
            foreach (var entity in dxfDoc.Entities.All)
            {
                switch (entity)
                {
                    case netDxf.Entities.Line line:
                        minX = Math.Min(minX, Math.Min(line.StartPoint.X, line.EndPoint.X));
                        minY = Math.Min(minY, Math.Min(line.StartPoint.Y, line.EndPoint.Y));
                        maxX = Math.Max(maxX, Math.Max(line.StartPoint.X, line.EndPoint.X));
                        maxY = Math.Max(maxY, Math.Max(line.StartPoint.Y, line.EndPoint.Y));
                        break;
                    case netDxf.Entities.Polyline2D pline:
                        foreach (var v in pline.Vertexes)
                        {
                            minX = Math.Min(minX, v.Position.X);
                            minY = Math.Min(minY, v.Position.Y);
                            maxX = Math.Max(maxX, v.Position.X);
                            maxY = Math.Max(maxY, v.Position.Y);
                        }
                        break;
                    case netDxf.Entities.Circle circle:
                        minX = Math.Min(minX, circle.Center.X - circle.Radius);
                        minY = Math.Min(minY, circle.Center.Y - circle.Radius);
                        maxX = Math.Max(maxX, circle.Center.X + circle.Radius);
                        maxY = Math.Max(maxY, circle.Center.Y + circle.Radius);
                        break;
                    case netDxf.Entities.Arc arc:
                        minX = Math.Min(minX, arc.Center.X - arc.Radius);
                        minY = Math.Min(minY, arc.Center.Y - arc.Radius);
                        maxX = Math.Max(maxX, arc.Center.X + arc.Radius);
                        maxY = Math.Max(maxY, arc.Center.Y + arc.Radius);
                        break;
                    case netDxf.Entities.MText mtext:
                        minX = Math.Min(minX, mtext.Position.X);
                        minY = Math.Min(minY, mtext.Position.Y);
                        maxX = Math.Max(maxX, mtext.Position.X);
                        maxY = Math.Max(maxY, mtext.Position.Y);
                        break;
                    case netDxf.Entities.Text text:
                        minX = Math.Min(minX, text.Position.X);
                        minY = Math.Min(minY, text.Position.Y);
                        maxX = Math.Max(maxX, text.Position.X);
                        maxY = Math.Max(maxY, text.Position.Y);
                        break;
                        // 可扩展更多实体类型
                }
            }
            if (minX == double.MaxValue || minY == double.MaxValue || maxX == double.MinValue || maxY == double.MinValue)
                return null;
            double partWidth = maxX - minX;
            double partHeight = maxY - minY;
            return new PartLayoutInfo
            {
                PartId = Guid.NewGuid().ToString(),
                Path = dxfPath,
                Width = partWidth,
                Height = partHeight,
                Position = new System.Windows.Point(0, 0), // 由布局算法设置
                PartRotation = 0
            };
        }


        /// 订阅事件以开始显示Sheet布局
        private void OnStartDisplaySheetLayout(string obj)
        {
            //todo: 这里可以根据obj参数来加载特定的Sheet布局
            TestData();
        }

        /// <summary>
        /// temporary test data
        /// </summary>
        private void TestData()
        {
            SheetLayoutInfo sheetLayoutInfo = new SheetLayoutInfo();
            sheetLayoutInfo.SheetId = "Sheet1";
            sheetLayoutInfo.Width = 4000;
            sheetLayoutInfo.Length = 5000;
            sheetLayoutInfo.Parts = new List<PartLayoutInfo>();

            _currentSheet = sheetLayoutInfo;

            _eventAggregator.GetEvent<DisplaySheetLayoutEvent>().Publish(sheetLayoutInfo);  
        }

        public void LoadLayoutFromJson(string jsonPath)
        {
            if (!File.Exists(jsonPath)) return;
            var json = File.ReadAllText(jsonPath);
            var sheet = JsonConvert.DeserializeObject<SheetLayoutInfo>(json);
            if (sheet != null)
            {
                //TODO: display events to display the sheet and parts
            }
        }

        /// <summary>
        /// 保存布局信息到数据库
        /// </summary>
        private async Task SaveLayoutAsync()
        {
            try
            {
                if (_currentSheet == null || _currentSheet.Parts == null || !_currentSheet.Parts.Any())
                {
                    System.Windows.MessageBox.Show("没有布局信息可保存", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                // 创建LayoutInfo对象
                var layoutInfo = new LayoutInfo
                {
                    LayoutMean = "2", // 合并布局
                    Merged = new MergedLayout
                    {
                        SheetLongth = _currentSheet.Length,
                        SheetWidth = _currentSheet.Width,
                        PartLayouts = new List<PartLayout>()
                    }
                };
                
                if (_currentSheet.Parts != null)
                {
                    foreach (var part in _currentSheet.Parts)
                    {
                        var partLayout = new PartLayout
                        {
                            SheetConsistentNo = part.PartId,
                            Position = new Position
                            {
                                X = part.Position.X,
                                Y = part.Position.Y
                            },
                            Rotation = part.PartRotation,
                            FilePath = part.Path

                        };
                        
                        layoutInfo.Merged.PartLayouts.Add(partLayout);
                    }
                }

                // 将布局信息转换为JSON字符串
                var layoutJson = JsonConvert.SerializeObject(layoutInfo, Formatting.Indented);

                // 生成MergedInfo：显示为布局中的PartLayoutInfo中的Path的文件名列表（多个文件名,隔开）
                var mergedInfo = string.Empty;
                if (_currentSheet.Parts != null && _currentSheet.Parts.Any())
                {
                    var fileNames = _currentSheet.Parts.Select(p => System.IO.Path.GetFileNameWithoutExtension(p.Path)).ToList();
                    mergedInfo = string.Join(",", fileNames);
                }

                // 发布布局信息更新领域事件，通知其他模块布局信息已更新
                _eventAggregator.GetEvent<LayoutInfoUpdatedEvent>().Publish(layoutInfo);

                // 显示保存成功消息
                System.Windows.MessageBox.Show("布局信息保存成功！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);

                ExecuteBack();

            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show($"保存布局信息失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 执行解除合并操作
        /// </summary>
        private void ExecuteRemoveGroup()
        {
            try
            {
                if (_currentMergedPlateAnnotationInfos == null || !_currentMergedPlateAnnotationInfos.Any())
                {
                    System.Windows.MessageBox.Show("没有可解除合并的数据", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                // 确认对话框
                var result = System.Windows.MessageBox.Show(
                    "确定要解除当前合并的布局吗？此操作将清除所有布局信息。", 
                    "确认解除合并", 
                    MessageBoxButton.YesNo, 
                    MessageBoxImage.Question);

                if (result == MessageBoxResult.Yes)
                {
                    // 发布解除合并事件，传递当前的PlateAnnotationInfo列表
                    _eventAggregator.GetEvent<UnmergeLayoutEvent>().Publish(_currentMergedPlateAnnotationInfos.ToList());

                    // 清除当前布局数据
                    _currentSheet = new SheetLayoutInfo();
                    _currentMergedPlateAnnotationInfos = null;

                    // 显示成功消息
                    System.Windows.MessageBox.Show("解除合并成功！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);

                    // 返回到主页面
                    ExecuteBack();
                }
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show($"解除合并失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}
